package com.jade.explorer.dirscan;

import java.io.File;
import java.util.ArrayList;

public class TreeParent extends TreeObject{
	
	
	//------------------------------Private fields
	/** List of children which contains in parent */
	private ArrayList<TreeObject> _children; 
	
	
	//------------------------------Private fields
	private boolean removeFromParent(String path, TreeParent p){
		for(int i = 0; i < p.count(); i++){			
			
			if(p.getChild(i).getPath().equalsIgnoreCase(path)){
				FileSystem.removeFile(p.getChild(i).getPath());
				p.removeByPos(i);
				return true;
			}
			
			if (p.getChild(i) instanceof TreeParent){
				if(removeFromParent(path, (TreeParent)p.getChild(i))) return true;
			}
		}
		return false;
	}
	
	private TreeParent searchParent(String path, TreeParent p){
		for(int i = 0; i < p.count(); i++){
			if(p.getChild(i) instanceof TreeParent){
				if(p.getChild(i).getPath().toLowerCase().equals(path.toLowerCase())){
					return (TreeParent)p.getChild(i);
				}
				if (searchParent(path, (TreeParent)p.getChild(i)) != null) return searchParent(path, (TreeParent)p.getChild(i));
			}
			if(p.getChild(i) instanceof TreeObject){
				if(p.getChild(i).getPath().toLowerCase().equals(path.toLowerCase())){
					return (TreeParent)p.getChild(i);
				}
			}
		}
		return null;
	}
	
	private boolean hasSameChild(TreeObject f, TreeParent p){
		
		for(int i = 0; i < p.count(); i++){
			if(p.getChild(i) instanceof TreeObject){
				if(p.getChild(i).getPath().toLowerCase().equals(f.getPath().toLowerCase())){
					return true;
				}
			}
			
			if(p.getChild(i) instanceof TreeParent){
				if(hasSameChild(f, (TreeParent)p.getChild(i))) return true;
			}
		}
		
		return false;
	}
	
	//------------------------------Constructors
	/**
	 * Creates <code>TreeParent</code> object with following parameters
	 * @param name name of current parent
	 * @param path path to folder of current parent
	 */
	public TreeParent(String name, String path) {
		super(name, path, FileType.FOLDER);
		_children = new ArrayList<TreeObject>();
	}
		
	
	//------------------------------Public methods
	/**
	 * Adds <code>TreeObject</code> child to <code>TreeParent</code> current parent
	 * @param child <code>TreeObject</code> to add
	 */
	public void addChild(TreeObject child) {
		_children.add(child);
		child.setParent(this);
	}
	
	
	/**
	 * Add new child by current path
	 * @param path <code>String</code> path to file
	 */
	public void addChildbyPath(String path){
		File file = new File(path);
		TreeObject to = new TreeObject(file.getName(), path);
		
		if(!hasSameChild(to, this)){
			if (searchParent(file.getParent().toString(), this) != null)
				searchParent(file.getParent().toString(), this).addChild(to);
			else System.err.println("ERROR: child parent was not found");
		}
	}
	
	/**
	 * Removes child from parent by <code>TreeObject</code> object
	 * @param child <code>TreeObject</code> parameter
	 */
	public void removeChild(TreeObject child) {
		_children.remove(child);
		child.setParent(null);
	}
	
	
	/**
	 * This method allows to get array of children which contains in this parent
	 * @return <code>TreeObject[]</code> array
	 */
	public TreeObject [] getChildren() {
		return (TreeObject [])_children.toArray(new TreeObject[_children.size()]);
	}
	
	
	/**
	 * Checks parent for children
	 * @return	<code>true</code> if this parent have children
	 */
	public boolean hasChildren() {
		return _children.size()>0;
	}
	
	
	/**
	 * Return number of child for this parent
	 * @return <code>int</code>
	 */
	public int count(){
		return _children.size();
	}
	
	/**
	 * This method removes child by name.
	 *  Also removes parent added as a child. 
	 * @param name <code>String</code> parameter, case is ignored
	 * @return true if have such child and removes it 
	 */
	public boolean removeChildByName(String name){
		if (hasChildren()){
			for(int i = 0; i < count(); i++){
				if(_children.get(i).getName().equalsIgnoreCase(name)){
					_children.remove(i);
					return true;
				}
			}
		}
		return false;
	}
	
	
	/**
	 * This method allows to get children name 
	 * @return	<code>String[]</code> list of children names 
	 */
	public String[] childrenList(){
		String[] list = new String[count()];
		for (int i = 0; i < count(); i++){
			list[i] += _children.get(i).getName();
		}
		return list;
	}
	
	
	/**
	 * Allows to remove any child from current parent,
	 * even if it belongs to a parent who is a child for this parent
	 * @param path <code>String</code> path to concrete object
	 * @return <code>true</code> if parent has child with current path and it successfully removed
	 */
	public boolean removeChildByPath(String path){
		return removeFromParent(path, this);
	}
	
	
	/**
	 * This method returns TreeObject by selected position in <code>ArrayList _childlist</code> of TreeParent
	 * @param pos numeric position of child in _childlist 
	 * @return	<code>TreeObject</code> by selected position
	 */
	public TreeObject getChild(int pos){
		return _children.get(pos);
	}
	
	
	/**
	 * This method removes selected child from <code>ArrayList _childlist</code> of TreeParent by position
	 * @param pos numeric position of child in _childlist
	 */
	public void removeByPos(int pos){
		_children.remove(pos);
	}
	
	
	/**
	 * This method removes all children from parent
	 */
	public void clear(){
		_children.clear();
	}
	
	
	public boolean hasChild(String path){
		
		for(int i = 0; i < _children.size(); i++){
			if (_children.get(i).getPath().toLowerCase().equals(path.toLowerCase()))
				return  true;
		}
		
		return false;
	}
	
	public void punishChild(String path){
		for(int i = 0; i < _children.size(); i++){
			if (_children.get(i).getPath().toLowerCase().equals(path.toLowerCase())){
				_children.remove(i);
				break;
			}
		}
	}
	
	public void punishAll(){
		_children.clear();
	}
}